//////////////////////////////////////////////////////////////////////////////
//
//  Created by Philip Mulcahy on 08/05/2012.
//  Copyright (c) 2012 Philip Mulcahy. All rights reserved.
//
//  This file is part of the note-recog library.
//
//  note-recog is free software: you can redistribute it and/or modify
//  it under the terms of version 3 of the GNU Lesser General Public License 
//  as published by the Free Software Foundation.
//
//  note-recog is distributed is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with note-recog.  If not, see <http://www.gnu.org/licenses/>.
//
//////////////////////////////////////////////////////////////////////////////

#ifndef note_recog_Spectrum_h
#define note_recog_Spectrum_h

#include <vector>
#include <memory>
#include <map>

#include "FastFourierTransform.h"

class Spectrum
{

//TODO Since this is an immutable class, share the expensive variables
//     between copies, using pointers - need to remember to use destructor.
private:
    Spectrum(); // not implemented
    const std::unique_ptr<std::vector<float> > _abs;
    const float _samplingFreq;
    const float _binWidthHz;
    const float _binCount;
    static std::map<float, const FastFourierTransform::Functor *> _fftCache;
    
public:    
    template< typename T >
    Spectrum(T begin, T end, float samplingFreq) :
      _abs(new std::vector<float>(begin, end)),
      _samplingFreq(samplingFreq),
      _binWidthHz(samplingFreq / (2.f * _abs->size())),
      _binCount(_abs->size())
    {}
    Spectrum(const Spectrum& rhs) :
      _abs(new std::vector<float>(*rhs._abs)),
      _samplingFreq(rhs._samplingFreq),
      _binWidthHz(rhs._binWidthHz),
      _binCount(rhs._binCount)
    {}
    static Spectrum fromTimeDomain(const std::vector<short>& timeDomain, float samplingFreq);
    float quality() const;
    float rms() const;
    float binwidthhz() const {return _binWidthHz;}
    float samplingFreq() const {return _samplingFreq;}
    const std::vector<float>& abs() const { return *_abs; }
};

#endif
